package com.anjubao.parking.municipal.parkinglot.service;

import com.alibaba.fastjson.JSONObject;
import com.anjubao.parking.municipal.common.dto.ApiCode;
import com.anjubao.parking.municipal.common.dto.ApiResult;
import com.anjubao.parking.municipal.common.exception.ServiceException;
import com.anjubao.parking.municipal.common.global.BusinessCodeEnum;
import com.anjubao.parking.municipal.common.utils.BeanUtils;
import com.anjubao.parking.municipal.common.utils.MunicipalParkingUtils;
import com.anjubao.parking.municipal.common.utils.U;
import com.anjubao.parking.municipal.parkinglot.constant.DeviceStatusEnum;
import com.anjubao.parking.municipal.parkinglot.constant.DeviceTypeEnum;
import com.anjubao.parking.municipal.parkinglot.dto.ParkingLotGeomagneticStatusDto;
import com.anjubao.parking.municipal.parkinglot.dto.ParkingLotSlotDto;
import com.anjubao.parking.municipal.parkinglot.dto.ParkingLotSlotFailureDto;
import com.anjubao.parking.municipal.parkinglot.dto.ParkingLotSlotReturnDto;
import com.anjubao.parking.municipal.parkinglot.feign.ParkingDeviceFeignClient;
import com.anjubao.parking.municipal.parkinglot.form.ParkingLotSlotForm;
import com.anjubao.parking.municipal.parkinglot.form.ParkingLotSlotScreeningForm;
import com.anjubao.parking.municipal.parkinglot.mapper.ParkingLotSlotMapper;
import com.anjubao.parking.municipal.parkinglot.model.ParkingLotSlot;
import com.anjubao.parking.municipal.parkinglot.util.FormTransfer;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.regex.Pattern;

/**
 * @author anjubao
 */
@Service
public class ParkingLotSlotService extends ServiceImpl<ParkingLotSlotMapper, ParkingLotSlot> {

    @Autowired
    private ParkingLotSlotMapper parkingLotSlotMapper;
    @Autowired
    private ParkingDeviceFeignClient parkingDeviceFeignClient;
    @Value("${roadSideParkingIp:http://192.168.41.147:8908/roadsideParking}")
    private String roadSideParkingIp;
    @Autowired
    private RestTemplate restTemplate;

    private static final String PATTERN="\\d{6}";

    /**
     * 新增泊位记录
     *
     * @param parkingLotSlotForm
     */
    public ParkingLotSlotReturnDto saveParkingLotSlot(ParkingLotSlotForm parkingLotSlotForm) {
        //判断name和泊位
        ParkingLotSlot slot = isSlot(parkingLotSlotForm);
        if (slot != null) {
            return null;
        }
        //生成id和code
        Long id = U.id();
        String code = MunicipalParkingUtils.generateCode(id, BusinessCodeEnum.PARKING_SLOT_CODE.getCode());
        //根据车场编号获取车场信息
        ParkingLotSlot parkingLot = parkingLotSlotMapper.selectByCode(parkingLotSlotForm.getParkingLotCode());
        //将车场信息与泊位信息合并
        ParkingLotSlot parkingLotSlot = FormTransfer.from2ParkingLotSlot(parkingLot, parkingLotSlotForm);
        parkingLotSlot.setId(id);
        parkingLotSlot.setCode(code);
        //向路边停车发送参数
        String url=roadSideParkingIp+"/sync/slots/1";
        ApiResult apiResult = getApiResult(id, code, parkingLotSlot, url);
        if (ApiCode.STATUS_OK.getCode() ==apiResult.getCode()){
            parkingLotSlotMapper.insert(parkingLotSlot);
            return new ParkingLotSlotReturnDto(code);
        }else {
            throw new ServiceException("泊位添加失败,请重试!") ;
        }
    }

    /**
     * 更新泊位记录
     *
     * @param parkingLotSlotForm
     * @param code
     * @return
     */
    public ParkingLotSlotReturnDto updateParkingLotSlotByCode(String code, ParkingLotSlotForm parkingLotSlotForm) {
        //判断name和泊位
        ParkingLotSlot slot = isSlot(parkingLotSlotForm);
        if (slot != null) {
            //如果泊位名称已经存在,根据泊位编号判断是不是当前的这条泊位记录
            if (!code.equals(slot.getCode())) {
                return null;
            }
        }
        //根据车场编号获取车场信息
        ParkingLotSlot parkingLot = parkingLotSlotMapper.selectByCode(parkingLotSlotForm.getParkingLotCode());
        //将车场信息与泊位信息合并
        ParkingLotSlot parkingLotSlot = FormTransfer.from2ParkingLotSlot(parkingLot, parkingLotSlotForm);
        //根据code获取id
        long id = MunicipalParkingUtils.getIdByCode(code);
        parkingLotSlot.setId(id);
        //向路边停车发送参数
        String url=roadSideParkingIp+"/sync/slots/2";
        ApiResult apiResult = getApiResult(id, code, parkingLotSlot, url);
        if (ApiCode.STATUS_OK.getCode() ==apiResult.getCode()){
            parkingLotSlotMapper.updateById(parkingLotSlot);
            return new ParkingLotSlotReturnDto(code);
        }else {
            throw new ServiceException("泊位更新失败,请重试!") ;
        }
    }

    /**
     * 抽取判断name格式和泊位是否重复度
     * @param parkingLotSlotForm
     * @return
     */
    private ParkingLotSlot isSlot(ParkingLotSlotForm parkingLotSlotForm) {
        //判断name是否是6位纯数字
        Pattern pattern = Pattern.compile(PATTERN);
        if (!pattern.matcher(parkingLotSlotForm.getName()).matches()) {
            throw new ServiceException("泊位编号必须为6位纯数字");
        }
        //根据泊位名称查询泊位是否存在
        QueryWrapper<ParkingLotSlot> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", parkingLotSlotForm.getName());
        return parkingLotSlotMapper.selectOne(queryWrapper);
    }

    /**
     * 抽取调路边停车的方法
     * @param id
     * @param code
     * @param parkingLotSlot
     * @param url
     * @return
     */
    private ApiResult getApiResult(Long id, String code, ParkingLotSlot parkingLotSlot, String url) {
        JSONObject object = new JSONObject();
        object.put("id", id);
        object.put("code", code);
        object.put("parkingLotCode", parkingLotSlot.getParkingLotCode());
        object.put("slotNum", parkingLotSlot.getName());
        /*object.put("isChargingSlot","true");
        object.put("charginghubNo",);
        object.put("charginghubGunNo","1");*/
        return this.restTemplate.postForObject(url, object, ApiResult.class);
    }

    /**
     * 根据泊位编号查询泊位记录
     *
     * @return
     */
    public ParkingLotSlotDto getParkingLotSlotByCode(String code) {
        QueryWrapper<ParkingLotSlot> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", code);
        ParkingLotSlot slot = parkingLotSlotMapper.selectOne(queryWrapper);
        return BeanUtils.transform(ParkingLotSlotDto.class, slot);
    }

    /**
     * 根据code删除parkingLotSlot
     *
     * @param code
     */
    public ParkingLotSlotReturnDto deleteParkingLotSlotByCode(String code) {
        //向路边停车发送参数
        String url=roadSideParkingIp+"/sync/slots/"+code+"/delete";
        JSONObject object = new JSONObject();
        object.put("parkingLotSlotCode", code);
        ApiResult apiResult = this.restTemplate.getForObject(url, ApiResult.class, object);
        if (ApiCode.STATUS_OK.getCode() ==apiResult.getCode()){
            parkingLotSlotMapper.deleteParkingLotSlot(code);
            return new ParkingLotSlotReturnDto(code);
        }else {
            throw new ServiceException("泊位删除失败,请重试!") ;
        }
    }

    /**
     * 分页
     *
     * @param page
     * @param pageSize
     * @param form
     * @return
     */
    public Page<ParkingLotSlotDto> getParkingLotSlots(Integer page, Integer pageSize, ParkingLotSlotScreeningForm form) {
        //初始化分页条件
        Page<ParkingLotSlotDto> pagination = new Page<>(page, pageSize);
        //根据搜索条件获取泊位信息
        List<ParkingLotSlotDto> parkingLotSlots = parkingLotSlotMapper.getFilterParkingLotSlots(pagination, form);
        //遍历泊位信息,设置泊位故障状态
        for (ParkingLotSlotDto parkingLotSlotDto : parkingLotSlots) {
            parkingLotSlotDto.setMalfunctionInfo(getResultDesc(parkingLotSlotDto));
        }
        return pagination.setRecords(parkingLotSlots);
    }

    /**
     * 根据车场code获取泊位列表
     *
     * @param parkingLotCode
     * @return
     */
    public List<ParkingLotSlotDto> getSlotsByParkingLotCode(String parkingLotCode, Integer type) {
        //分设备查询剩余泊位
        if (type == DeviceTypeEnum.CHARGING_PILE.getCode()) {
            //调用接口获取安装了充电桩的泊位id
            List<Long> slotCodeChargingList = parkingDeviceFeignClient.selectCharging(parkingLotCode).getResult();
            //查询不包含充电桩的泊位列表
            return parkingLotSlotMapper.getSlotCodes(parkingLotCode,slotCodeChargingList);
        } else if (type == DeviceTypeEnum.VIDEO_PILE.getCode()) {
            //调用接口获取安装了视频桩的泊位id
            List<Long> slotCodeVideoList = parkingDeviceFeignClient.selectVideo(parkingLotCode).getResult();
            //查询不包含视频桩的泊位列表
            return parkingLotSlotMapper.getSlotCodes(parkingLotCode,slotCodeVideoList);
        } else {
            //调用接口获取安装了地磁的泊位id
            List<Long> slotCodeGeomagneticList = parkingDeviceFeignClient.selectGeomagnetic(parkingLotCode).getResult();
            //查询指定车场不包含地磁的泊位列表
            return parkingLotSlotMapper.getSlotCodes(parkingLotCode,slotCodeGeomagneticList);
        }
    }

    /**
     * 得到故障类型
     *
     * @param parkingLotSlotDto
     * @return
     */
    private String getResultDesc(ParkingLotSlotDto parkingLotSlotDto) {
        //根据泊位编号获取设备类型和状态
        List<ParkingLotSlotFailureDto> failureDtos = parkingDeviceFeignClient.selectDevices(parkingLotSlotDto.getCode()).getResult();
        StringBuffer result = new StringBuffer();
        for (ParkingLotSlotFailureDto failureDto : failureDtos) {
            int type = failureDto.getType();
            int status = failureDto.getStatus();
            switch (DeviceTypeEnum.getByCode(type)) {
                case CHARGING_PILE:
                    result.append("充电桩");
                    break;
                case VIDEO_PILE:
                    result.append("视频桩");
                    break;
                case GEOMAGNETIC_SENSOR:
                    result.append("地磁");
                    break;
                case PDA:
                    result.append("pda");
                    break;
                case GUIDANCE_SCREEN:
                    result.append("诱导屏");
                    break;
                default:
                    break;
            }
            switch (DeviceStatusEnum.getByCode(status)) {
                case Breakdown:
                    result.append("禁用 ");
                    break;
                case Forbiddance:
                    result.append("故障 ");
                    break;
                case Normal:
                    result.append("正常 ");
                    break;
                default:
                    break;
            }
        }
        return result.toString();
    }

    /**
     * 根据泊位code获取车位列表
     * @param parkingLotSlotName
     * @return
     */
    public List<ParkingLotSlotDto> getParkingLotSlotIdsByName(String parkingLotSlotName) {
        return parkingLotSlotMapper.getParkingLotSlotIdsByName(parkingLotSlotName);
    }
    /**
     * 根据泊位code获取停车场信息
     * @param parkingLotSlotCode
     * @return
     */
    public ParkingLotGeomagneticStatusDto getParkingLotByParkingLotSlotCode(String parkingLotSlotCode) {
        return parkingLotSlotMapper.getParkingLotByParkingLotSlotCode(parkingLotSlotCode);
    }

    /**
     * 更新车位状态
     * @param code
     * @param status
     * @return
     */
    public ParkingLotSlotReturnDto updateParkingLotSlotsStatus(String code, Integer status) {
        ParkingLotSlot parkingLotSlot=new ParkingLotSlot();
        parkingLotSlot.setStatus(status);
        parkingLotSlot.setId(MunicipalParkingUtils.getIdByCode(code));
        parkingLotSlotMapper.updateById(parkingLotSlot);
        return new ParkingLotSlotReturnDto(code);
    }

    public ParkingLotSlot getParkingLotByName(String parkinglotSlotName) {
        ParkingLotSlot parkingLotSlot = parkingLotSlotMapper.selectOne(new QueryWrapper<>(new ParkingLotSlot().setName(parkinglotSlotName)));
        if (null == parkingLotSlot) {
            throw new ServiceException("停车位不存在");
        }
        return parkingLotSlot;

    }
}
